March 24, 2021
Browser History API를 이용해 구현하는 지하철 노선도 관리 SPA
유저는 회원 가입을 할 수 있다,
email
, name
, password
이다.유저는 로그인 할 수 있다.
유저는 로그아웃할 수 있다.
access token
이 만료된 경우, 사용자를 로그아웃 시키고 로그인 화면으로 이동시킨다.그동안 기능 단위로 모듈을 분리하며 미션을 진행 했습니다.
이번 미션을 진행하면서도 Handler와 View를 나누어 기능 단위로 작게 모듈을 분리하면서 진행하려는 계획이 있었습니다. 그러나 이번 미션 페어인 곤이가 Component단위로 모듈을 분리하면서 진행하면 어떻겠냐는 의견을 제시해줬습니다.
Component 단위로 모듈을 분리하니 각각의 Component에서 수행할 역할들을 한 곳에 모아서 관리할 수 있어 좋았습니다. 또한 반복되는 코드를 Class로 추상화 시켜 extends를 통해 확장하며 사용해가니 코드를 작성하기도 한결 편해졌습니다.
다만, 각 Component가 수행할 동작들은 하나의 Class에 모두 정의하다보니 Class가 비대해진다는 느낌을 받았습니다.
지난 미션을 진행하면서 API Key를 숨기기 위해 Webpack을 알아보았습니다. 하지만 Webpack을 실제 프로젝트에 적용해 번들링 하는 단계까지는 나아가지 못 했습니다.
이번 미션 요구사항 중 Webpack을 통한 번들링
부분이 있어 지난 미션을 진행하며 학습했던 webpack을 적용해 볼 수 있었습니다.
webpack을 실제 적용하기 위해
SPA를 구현하기 위해 Router를 만들어야 했습니다.
전통적인 Link 방식과 AJAX를 통한 방식을 공부했습니다.
Hsah를 이용한 라우터를 구현은 SEO 이슈가 존재해 History API를 통한 PJAX방식으로 구현했습니다.
기존 API 요청을 보내는 코드는 다음과 같이 작성되어 있었습니다.
const option = {
post: (contents) => ({
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=UTF-8',
},
body: JSON.stringify(contents),
}),
...
};
const request = async (url, option = {}) => {
try {
const response = await fetch(`${BASE_URL}${url}`, option);
if (!response.ok) {
throw new Error(response.message);
}
return response;
} catch (err) {
throw err;
}
};
export const API = {
signup: ({ email, password, name }) => {
return request('/members', option.post({ email, password, name }));
}
...
}
API 요청을 보낼 때 request(URL, 옵션)
이런식으로 사용하고 있었는데 request.옵션(URL)
과 같은 형식으로 보내는게 더 좋을거 같다는 피드백을 받았습니다.
피드백을 받고 API요청을 다음과 같은 형식으로 변경했습니다.
const _request = async (url, option = {}) => {
try {
const response = await fetch(`${BASE_URL}${url}`, option);
if (!response.ok) {
throw response.status;
}
return response;
} catch (status) {
throw status;
}
};
const request = {
post: async (info) => {
const { url, contents, token } = info;
const option = {
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=UTF-8',
},
body: JSON.stringify(contents),
};
if (token) {
option.headers.Authorization = `Bearer ${token}`;
}
return _request(url, option);
},
...
}
export const API = {
signup: ({ email, password, name }) => {
return request.post({
url: '/members',
contents: { email, password, name },
});
},
...
}
다음과 같은 형식으로 변경하니 확실히 어떤 메서드를 사용해 요청을 보내는지 일목요연하게 확인할 수 있었습니다.
전체 구조를 컴포넌트 구조로 가져가면서 다음과 같이 API 요청을 컴포넌트들에서 직접 보내는 방식을 사용했습니다.
이 방식을 사용하면 response에 대한 핸들링도 컴포넌트에서 진행하고 있었고 피드백 내용처럼 해당 API를 다른 곳에서 호출할 때 중복된 코드가 생긴다는 문제가 있었습니다.
리뷰어 분의 피드백을 적용해 중간에 Service 레이어를 두고 컴포넌트에서는 요청에 대한 데이터만 받아서 사용하니 훨씬 코드가 깔끔해지고 중복이 줄어들었습니다. 또한 레이어를 분리함으로 인해 각각의 역할과 책임이 분명해졌습니다.